// 实现生成随机key
function getUniKey(obj) {
  var unique_key = new Date().getTime() + '-' +Math.random() + '';
  if(obj.hasOwnProperty(unique_key)) {
    getUniKey(obj);
  } else {
    return unique_key;
  }
}
Function.prototype.myApply = function(context) {
  var context = context || window;
  // 考虑当前fn属性存在命名重合覆盖
  var fn = getUniKey(context);
  context[fn] = this;
  var args = [];
  var arr = arguments[1];
  console.log('arguments', arguments)
  console.log('arr', arr)
  var result = null;
  var es6Result = null;
  if(!arr) {
    var noParams = context[fn]();
    delete context[fn];
    return noParams;
  }
  for(var i = 0, len = arr.length; i < len; i++) {
    args.push('arr[' + i + ']');
  };
  // eval实现
  result = eval('context[fn](' + args + ')');
  // es6扩展运算符实现
  // es6Result = context[fn](...arr);
  delete context[fn];
  return result;
}
//原生JavaScript封装call方法
Function.prototype.myCall = function(context) {
  var result = this.myApply([].shift.myApply(arguments), arguments);
  return result;
}
// 原生实现bind
Function.prototype.myBind = function(context) {
  var self = this;
  console.log([].slice.myCall(arguments))
  return function() {
    return self.myApply(context, [].slice.myCall(arguments,1))
  }
}
var test1 = {
  name: 'test1',
  say: function(age, sex) {
    console.log('name', this.name, age, sex);
    console.log('age', age);
    console.log('sex', sex);
    return {
      name: this.name,
      age: age,
      sex: sex,
    }
  }
}
var test2 = {
  name: 'test2'
};
// var result = test1.say.myApply(test2, [24, 'man']);
// var result = test1.say.myCall(test2, 24, 'man');
var testBind = test1.say.myBind(test2, 24, 'man');
console.log('testBind', testBind)
testBind();
// console.log('result', result);